package org.chs.ts.batch.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Compay 盛唐天行
 * @Author: wuwei
 * @Censor By wuwei
 * @Sence 2023/5/25 13:56
 * @Modify 2023/5/25 13:56
 * @Description
 */
@Slf4j
public class CommonUtil {
    /**
     * 获取本地ip（ipv4）
     *
     * @return 本地ip（ipv4）
     */
    public static String getLocalHostAddress() {
        //定义网络接口枚举类
        Enumeration<NetworkInterface> allNetInterfaces;
        try {//获得网络接口
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            //声明一个InetAddress类型ip地址
            //遍历所有的网络接口
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = allNetInterfaces.nextElement();
                if (!isValidInterface(netInterface)) {
                    continue;
                }
                //同样再定义网络地址枚举类
                Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress candidateAddress = addresses.nextElement();
                    //InetAddress类包括Inet4Address和Inet6Address
                    if ((candidateAddress instanceof Inet4Address) && !candidateAddress.isLoopbackAddress()) {
                        return candidateAddress.toString().substring(1);
                    }
                }
            }
        } catch (SocketException e) {
            log.error("获取服务端ip地址出错，异常信息：", e);
        }
        return "127.0.0.1";
    }

    /**
     * 过滤回环网卡、点对点网卡、非活动网卡、虚拟网卡
     *
     * @param ni 网卡
     * @return 如果满足要求则true，否则false
     */
    private static boolean isValidInterface(NetworkInterface ni) throws SocketException {
        return !ni.isLoopback() && !ni.isPointToPoint() && ni.isUp() && !ni.isVirtual();
    }

    /**
     * logInfo 统一打印日志
     *
     * @param infoList   打印信息列表
     * @param infoPrefix 打印信息前缀
     */
    public static void showLogInfo(List infoList, String infoPrefix) {
        StringBuilder infoMessage = new StringBuilder();
        for (Object o : infoList) {
            infoMessage.append("item -> ").append(o.toString()).append("##");
        }
        log.info(infoPrefix + ":" + infoMessage);
    }


    public static String getHHmmss(Date date) {
        return getDateTimeByFormat(date, "HHmmss");
    }

    public static String getHHmmssByDiffDateHour(Date date, int diffDate) {

        return getDateStringByDiffDateFromDateFormat(date, Calendar.HOUR, diffDate, "HHmmss");
    }

    private static String getDateStringByDiffDateFromDateFormat(Date date, int CalendarType, int diffDate, String DateFormat) {

        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(CalendarType, diffDate);
        return new SimpleDateFormat(DateFormat).format(calendar.getTime());
    }


    public static String getYYYYMMdd(Date date) {
        return getDateTimeByFormat(date, "yyyyMMdd");
    }

    public static String getFullDateTime(Date date) {
        return getDateTimeByFormat(date, "yyyyMMddHHmmss");
    }

    public static String getFullDateTimeByDiffDateHour(Date date, int diffDate) {
        return getDateStringByDiffDateFromDateFormat(date, Calendar.HOUR, diffDate, "yyyyMMddHHmmss");
    }

    public static String getDateTimeByDiffDateHour(Date date, int diffDate) {
        return getDateStringByDiffDateFromDateFormat(date, Calendar.HOUR, diffDate, "yyyyMMdd");
    }

    public static String getFullDateTimeByDiffDate(Date date, int diffDate) {
        return getDateStringByDiffDateFromDateFormat(date, Calendar.DATE, diffDate, "yyyyMMddHHmmss");
    }

    public static String getDateTimeByFormat(Date date, String dateFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        return sdf.format(date);
    }

    public static String getDayByParameter(String corDay, int diffDate) {
        Date date;
        try {
            date = (new SimpleDateFormat("yyyyMMdd")).parse(corDay);
        } catch (ParseException e) {
            date = new Date();
            log.error("getDayByParameter 日期转换 异常！入参[后管平台]->[核心日期]： " + corDay);
        }
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 比较当前 时间 是否 在日切时间之后
        calendar.add(Calendar.DATE, diffDate);
        return new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
    }

    public static void showRunningMsg(String className, String method, JSONObject taskParams, JSONObject taskStepParams) {
        log.info("----------------------" + className + " -> " + method + " Running --------------------------");
        if (!taskParams.isEmpty() || !taskStepParams.isEmpty()) {
            log.info("----------------------" + className + " -> " + method + " Parameters --------------------------");
            Field[] taskParamsFields = taskParams.getClass().getDeclaredFields();
            Field[] taskStepParamsFields = taskStepParams.getClass().getDeclaredFields();

            List<Field> paramKeys =
                    Stream.concat(Arrays.stream(taskParamsFields), Arrays.stream(taskStepParamsFields)).distinct().collect(Collectors.toList());

            for (Field item : paramKeys) {
                String key = item.getName();
                if (taskStepParams.containsKey(key)) {
                    log.info("----------------------Parameter : taskStepParams -> " + key + " [" + taskStepParams.getString(key) + "] " +
                            "--------------------------");
                    continue;
                }
                log.info("----------------------Parameter : taskParams -> " + key + " [" + taskParams.getString(key) + "] " +
                        "--------------------------");

            }

        }
    }

    /**
     * 针对 未使用 taskParams 监测 跑批任务 taskParams 配置情况，对于 配置 taskParams 输出相关信息
     */
    public static void invalidParamMsg(String className, String method, JSONObject taskParams, JSONObject taskStepParams) {
        if (!taskParams.isEmpty() || !taskStepParams.isEmpty()) {
            log.info("----------------------" + className + " -> " + method + " invalid Parameters --------------------------");
            Field[] taskParamsFields = taskParams.getClass().getDeclaredFields();
            Field[] taskStepParamsFields = taskStepParams.getClass().getDeclaredFields();

            List<Field> paramKeys =
                    Stream.concat(Arrays.stream(taskParamsFields), Arrays.stream(taskStepParamsFields)).distinct().collect(Collectors.toList());

            for (Field item : paramKeys) {
                String key = item.getName();
                if (taskStepParams.containsKey(key)) {
                    log.info("----------------------invalid Parameter : taskStepParams -> " + key + " [" + taskStepParams.getString(key) + "] " +
                            "--------------------------");
                    continue;
                }
                log.info("----------------------invalid Parameter : taskParams -> " + key + " [" + taskParams.getString(key) + "] " +
                        "--------------------------");

            }

        }
    }
}
